This section supplies a sample program that implements a derived media handler component for PICT images.
Listing 10-1 supplies the component dispatchers for the media handler component for PICT images together with the required functions.
Listing 1 Implementing the required functions
typedef struct {
ComponentInstance self;
ComponentInstance parent;
ComponentInstance delegateComponent;
Fixed width;
Fixed height;
MatrixRecord matrix;
Media media;
Track track;
} PictGlobalsRecord, *PictGlobals;
pascal ComponentResult PictMediaDispatch
(ComponentParameters *params,
Handle storage)
{
OSErr err = badComponentSelector;
ComponentFunction componentProc = 0;
switch (params->what) {
case kComponentOpenSelect:
componentProc = PictOpen; break;
case kComponentCloseSelect:
componentProc = PictClose; break;
case kComponentCanDoSelect:
componentProc = PictCanDo; break;
case kComponentVersionSelect:
componentProc = PictVersion; break;
case kComponentTargetSelect:
componentProc = PictVersion; break;
case kMediaInitializeSelect:
componentProc = PictInitialize; break;
case kMediaIdleSelect:
componentProc = PictIdle; break;
case kMediaSetDimensionsSelect:
componentProc = PictSetDimensions; break;
case kMediaSetMatrixSelect:
componentProc = PictSetMatrix; break;
}
if (componentProc)
err = CallComponentFunctionWithStorage (storage, params,
componentProc);
else
err = DelegateComponentCall (params, ((PictGlobals)
storage)->delegateComponent);
return err;
}
pascal ComponentResult PictCanDo (PictGlobals globals,
short ftnNumber)
{
switch (ftnNumber) {
case kComponentOpenSelect:
case kComponentCloseSelect:
case kComponentCanDoSelect:
case kComponentVersionSelect:
case kComponentTargetSelect:
case kMediaInitializeSelect:
case kMediaIdleSelect:
case kMediaSetDimensionsSelect:
case kMediaSetMatrixSelect:
return true;
default:
return ComponentFunctionImplemented
(globals->delegateComponent, ftnNumber);
}
}
pascal ComponentResult PictVersion (PictGlobals globals)
{
return 0x00020001;
}
pascal ComponentResult PictOpen(PictGlobals globals,
ComponentInstance self)
{
OSErr err;
/* allocate storage */
globals = (PictGlobals)NewPtrClear(sizeof(PictGlobalsRecord));
if (err = MemError()) return err;
SetComponentInstanceStorage(self, (Handle)globals);
globals->self = self;
globals->parent = self;
/* find a base media handler to serve as a delegate */
globals->delegateComponent =
OpenDefaultComponent (MediaHandlerType,
BaseMediaType);
if (globals->delegateComponent)
PictTarget(globals, self); /* set up the calling chain */
else {
DisposePtr((Ptr)globals);
err = cantOpenHandler;
}
return err;
}
pascal ComponentResult PictClose (PictGlobals globals,
ComponentInstance self)
{
if (globals) {
if (globals->delegateComponent)
CloseComponent(globals->delegateComponent);
DisposePtr((Ptr)globals);
}
return noErr;
}
pascal ComponentResult PictTarget(PictGlobals store,
ComponentInstance parentComponent)
{
/* remember who is at the top of your calling chain */
store->parent = parentComponent;
/* and inform your delegate component of the change */
ComponentSetTarget(store->delegateComponent, parentComponent);
return noErr;
}
The derived media handler component is initialized by the Movie Toolbox's calling of the MediaInitialize function (described on MediaInitialize ). You should then report the derived media handler capabilities to the base media handler before the Movie Toolbox starts working with your media by calling the MediaSetHandlerCapabilities function (described on MediaSetHandlerCapabilities ) from your MediaInitialize function.
Listing 10-2 is the initialization function for a derived media handler. The PictInitialize function stores the initial height, width, track movie matrix, media, and track of the derived media handler component. From PictInitialize , the MediaSetHandlerCapabilities function is called to inform the base media handler of its existence and features.
Listing 2 Initializing a derived media handler
pascal ComponentResult PictInitialize (PictGlobals store,
GetMovieCompleteParams *gmc)
{
/* remember some useful parameters */
store->width = gmc->width;
store->height = gmc->height;
store->matrix = gmc->trackMovieMatrix;
store->media = gmc->theMedia;
store->track = gmc->theTrack;
/* tell the base media handler about your derived
media handler */
MediaSetHandlerCapabilities(store->delegateComponent,
handlerHasSpatial, handlerHasSpatial);
return noErr;
}
The Movie Toolbox provides processing time to your derived media handler to display samples by calling the MediaIdle function (described on MediaIdle ). Your media handler may use this time to play its media sample. The code in Listing 10-3 allows the derived media handler component to draw the current media sample (in this case, a PICT image).
Listing 3 Drawing the media sample
pascal ComponentResult PictIdle (PictGlobals store,
TimeValue atMediaTime,
long flagsIn, long *flagsOut,
const TimeValue *tr)
{
OSErr err;
Rect r;
Handle sample = NewHandle (0);
if (err = MemError()) goto bail;
/* get the current sample */
err = GetMediaSample (store->media, sample, 0, nil,
atMediaTime, nil, 0, 0, 0, 0, 0, 0);
if (err) goto bail;
/* draw it using the current matrix */
SetRect (&r, 0, 0, FixRound (store->width),
FixRound (store->height));
TransformRect (&store->matrix, &r, nil);
EraseRect (&r);
DrawPicture ((PicHandle)sample, &r);
bail:
DisposeHandle (sample);
*flagsOut |= mDidDraw; /* let Movie Toolbox know you drew
something */
return err;
}
pascal ComponentResult PictSetDimensions (PictGlobals store,
Fixed width,
Fixed height)
{
/* remember the new track */
store->width = width;
store->height = height;
return noErr;
}
pascal ComponentResult PictSetMatrix (PictGlobals store,
MatrixRecord *trackMovieMatrix)
{
/* remember the new display matrix */
store->matrix = *trackMovieMatrix;
return noErr;
}